/* @flow */

import config from "../config.js";
import { initUse } from "./use.js";
import { initMixin } from "./mixin.js";
import { initExtend } from "./extend.js";
import { initAssetRegisters } from "./assets.js";
import { set, del } from "../observer/index.js";
import { ASSET_TYPES } from "shared/constants.js";
import builtInComponents from "../components/index.js";
import { observe } from "core/observer/index.js";

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive,
} from "../util/index.js";

export function initGlobalAPI(Vue: GlobalAPI) {
  // config
  const configDef = {};
  configDef.get = () => config;
  if (process.env.NODE_ENV !== "production") {
    configDef.set = () => {
      warn(
        "Do not replace the Vue.config object, set individual fields instead."
      );
    };
  }
  // 初始化静态属性config
  Object.defineProperty(Vue, "config", configDef);

  // exposed util methods.
  // NOTE: these are not considered part of the public API - avoid relying on
  // them unless you are aware of the risk.
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive,
  };
  //   挂载全局set,delete,nextTick方法
  Vue.set = set;
  Vue.delete = del;
  Vue.nextTick = nextTick;

  // 2.6 explicit observable API
  // 挂载全局observable 让一个对象可响应
  Vue.observable = <T>(obj: T): T => {
    observe(obj);
    return obj;
  };
  // 初始化一个轻量的对象options
  Vue.options = Object.create(null);
  //   初始化component,directive,filter到options
  ASSET_TYPES.forEach((type) => {
    Vue.options[type + "s"] = Object.create(null);
  });

  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  Vue.options._base = Vue;
  //   将keep-alive注册到全局组件中
  extend(Vue.options.components, builtInComponents);
  // 初始化Vue.use方法 用来注册插件
  initUse(Vue);
  //   初始化Vue.mixin方法 实现混入
  initMixin(Vue);
  //   初始化Vue.extend方法 基于传入的option返回一个组件的构造函数
  initExtend(Vue);
//   注册 Vue.directive() Vue.component() Vue.filter()
  initAssetRegisters(Vue);
}
